//the r mean the M read S the w is samilar
`define WAIT_ADDR 1'b0
`define WAIT_DATA 1'b1
module MODULE_AXI_Lite_S
#(
	DWIDTH = 64,
	AWIDTH = 32,
	MASKLEN= 8
)
(
	input										clk_i,
	input 									rst_i,
	//connect with the S module for read
	input			[DWIDTH-1:0]	data_r_i,
	input										data_r_valid_i, //this valid main the data_i is valid
	output		[AWIDTH-1:0]	addr_r_o,
	output									addr_r_valid_o,

	//connect with the S module for write 
	output	 	[DWIDTH-1:0]	data_w_o,
	output		[MASKLEN-1:0]	data_w_mask_o,
	output									data_w_valid_o,
	output		[AWIDTH-1:0]	addr_w_o,
	input										data_w_end_i,

	//AXI-lite
	input			[AWIDTH-1:0]	araddr_i,
	input										arvalid_i,
	output									arready_o,

	output		[DWIDTH-1:0]	rdata_o,
	output		[1:0]					rresp_o, //not handled yet just out 2'b0
	output									rvalid_o,
	input										rready_i,
	
	input			[AWIDTH-1:0]	awaddr_i,
	input										awvalid_i,
	output									awready_o,

	input			[DWIDTH-1:0]	wdata_i,
	input			[MASKLEN-1:0]	wstrb_i,
	input										wvalid_i,
	output									wready_o,

	output		[1:0]					bresp_o,//not finished 
	output									bvalid_o,//not...
	input										bready_i//not...
);
/////////////////////////////////state machine read start/////////////////////////////////
wire r_state_now;
wire r_state_next;
//reg for state
Reg #(1,0)	r_state (clk_i,rst_i,r_state_next,r_state_now,1);
// choose the next state
MuxKeyWithDefault #(2,1,1) mux_r_state_next(.out(r_state_next),.key(r_state_now),.default_out(0),.lut({
	`WAIT_ADDR,	(arvalid_i & arready_o)? `WAIT_DATA : `WAIT_ADDR,
	`WAIT_DATA,	(rready_i&rvalid_o) ? `WAIT_ADDR:`WAIT_DATA
	}));
//decide signals according to the state
assign rdata_o[DWIDTH-1:0] = data_r_i[DWIDTH-1:0];
assign rvalid_o = r_state_now & (~rst_i) &data_r_valid_i;
assign arready_o = ~r_state_now & (~rst_i); //& valid_i;
assign rresp_o = 2'b0; //not finished yet

//reg for address and arvalid
wire write_addr_reg_en;
assign write_addr_reg_en = (r_state_now == `WAIT_ADDR) & arvalid_i&arready_o;
Reg #(AWIDTH,0) addr_r(clk_i,rst_i,araddr_i[AWIDTH-1:0],addr_r_o[AWIDTH-1:0],write_addr_reg_en);
Reg #(1,0) addr_valid(clk_i,rst_i,write_addr_reg_en,addr_r_valid_o,1);
/////////////////////////////////state machine read end/////////////////////////////////


/////////////////////////////////state machine write start///////////////////////////
wire w_state_now;
wire w_state_next;
//reg for state
Reg #(1,0)	w_state (clk_i,rst_i,w_state_next,w_state_now,1);
// choose the next state
MuxKeyWithDefault #(2,1,1) mux_w_state_next(.out(w_state_next),.key(w_state_now),.default_out(0),.lut({
	`WAIT_ADDR,	awready_o & awvalid_i ? `WAIT_DATA : `WAIT_ADDR,
	`WAIT_DATA, wvalid_i & wready_o ? `WAIT_ADDR :	`WAIT_DATA
}));

assign awready_o = ~w_state_now &(~rst_i);
assign wready_o = w_state_now &(~rst_i)&data_w_end_i;
// reg for singals;
wire write_addr_w_reg_en;
assign write_addr_w_reg_en = (w_state_now == `WAIT_ADDR) & awvalid_i & awready_o;
Reg #(AWIDTH,0) addr_w(clk_i,rst_i,awaddr_i[AWIDTH-1:0],addr_w_o[AWIDTH-1:0],write_addr_w_reg_en);
wire write_data_reg_en;
assign write_data_reg_en = (w_state_now == `WAIT_DATA)& wvalid_i;
Reg #(DWIDTH,0) data_w(clk_i,rst_i,wdata_i[DWIDTH-1:0],data_w_o[DWIDTH-1:0],write_data_reg_en);
Reg #(MASKLEN,0) mask_w(clk_i,rst_i,wstrb_i[MASKLEN-1:0],data_w_mask_o[MASKLEN-1:0],write_data_reg_en);
Reg #(1,0) w_data_valid(clk_i,rst_i,write_data_reg_en,data_w_valid_o,1);



/////////////////////////////////state machine write end///////////////////////////
endmodule
